<script setup lang="ts">
import { message } from '@/components/XtxUI';
import type { SkuEmit } from '@/components/XtxUI/Sku/index.vue';
import { useCartStore, useGoodsStore } from '@/store';
import type { CartItem } from '@/types';
import { storeToRefs } from 'pinia';
import { ref } from 'vue';
import { useRoute } from 'vue-router';
import MyCount from '../Test/components/MyCount.vue';
import GoodsHot from './components/goods-hot.vue';
import GoodsDetail from './components/goods-detail.vue';
import GoodsSales from './components/goods-sales.vue';

const goods = useGoodsStore();
// 获取 路由信息
const route = useRoute();
goods.getGoodsDetail(route.params.id as string);
const { goodsDetail } = storeToRefs(goods);

const count = ref<number>(1);
// 规格组件 SKU 变化
const skuId = ref(''); // 下单的时候需要用到 skuId，现在提前收集
const specsText = ref(''); // 选中规格说明
const skuChange = (val: SkuEmit) => {
  skuId.value = val.skuId || '';
  specsText.value = val.specsText || '';
  // 类型守卫，排除掉 undefined 情况，规格确定的情况下才更新
  if (goodsDetail.value && val.skuId) {
    // 更新最新价格
    goodsDetail.value.price = val.price;
    // 更新原价格
    goodsDetail.value.oldPrice = val.oldPrice;
    // 更新库存
    goodsDetail.value.inventory = val.inventory;
  }
};
// 加入购物车
const addCartBtn = () => {
  if (!skuId.value) {
    return message({ type: 'warn', text: '请选择商品规格~' });
  }
  if (!goodsDetail.value) return;
  const cart = useCartStore();
  const cartItem = {
    // 第一部分：商品详情中有的
    id: goodsDetail.value.id, // 商品id
    name: goodsDetail.value.name, // 商品名称
    picture: goodsDetail.value.mainPictures[0], // 图片
    price: goodsDetail.value.oldPrice, // 旧价格
    nowPrice: goodsDetail.value.price, // 新价格
    stock: goodsDetail.value.inventory, // 库存
    // 第二部分：商品详情中没有的，自己通过响应式数据收集
    count: count.value, // 商品数量
    skuId: skuId.value, // skuId
    attrsText: specsText.value, // 商品规格文本
    // 第三部分：设置默认值即可
    selected: true, // 默认商品选中
    isEffective: true, // 默认商品有效
  } as CartItem;
  cart.addCart(cartItem);
};
</script>
​
<template>
  <div class="xtx-goods-page">
    <div class="container">
      <!-- 面包屑 -->
      <XtxBread>
        <XtxBreadItem to="/">首页</XtxBreadItem>
        <XtxBreadItem :to="`/category/${goodsDetail?.categories[1].id}`">
          {{ goodsDetail?.categories[1].name }}
        </XtxBreadItem>
        <XtxBreadItem :to="`/category/sub/${goodsDetail?.categories[0].id}`">
          {{ goodsDetail?.categories[0].name }}
        </XtxBreadItem>
        <XtxBreadItem>{{ goodsDetail?.name }}</XtxBreadItem>
      </XtxBread>
      <!-- 商品信息 -->
      <div v-if="goodsDetail" class="goods-info">
        <!-- 图片预览区 -->
        <div class="media">
           
          <!-- 图片预览区 -->
           
          <XtxImageView :image-list="goodsDetail?.mainPictures" />
          <!-- 区域2 商品销售信息组件 -->
          <GoodsSales />
        </div>
        <!-- 商品信息区 -->
        <div class="spec">
          <!-- 商品主要信息 -->
          <div class="goods-main">
            <p class="g-name">{{ goodsDetail?.name }}</p>
            <p class="g-desc">{{ goodsDetail?.desc }}</p>
            <p class="g-desc">这是选中的商品规格</p>
            <p class="g-price">
              <span>{{ goodsDetail?.price }}</span>
              <span>{{ goodsDetail?.oldPrice }}</span>
            </p>
            <div class="g-service">
              <dl>
                <dt>促销</dt>
                <dd>12月好物放送，App领券购买直降120元</dd>
              </dl>
              <dl>
                <dt>配送</dt>
                <dd>至</dd>
                <dd>
                  <XtxCity />
                </dd>
              </dl>
              <dl>
                <dt>服务</dt>
                <dd>
                  <span>无忧退货</span>
                  <span>快速退款</span>
                  <span>免费包邮</span>
                  <a href="javascript:;">了解详情</a>
                </dd>
              </dl>
            </div>
          </div>
          <!-- 规格选择组件 -->
          <XtxSku :goods="goodsDetail" @change="skuChange" />
          <!-- 数量选择组件 -->
          <MyCount is-label v-model="count" :min="1" :max="goodsDetail.inventory"></MyCount>
          <!-- 按钮组件 -->
          <XtxButton @click="addCartBtn()" style="margin-top: 20px" type="primary" size="middle">加入购物车</XtxButton>
        </div>
      </div>
      <div v-else class="goods-info xtx-loading"></div>
      <!-- 商品详情 -->
      <div class="goods-footer">
        <div class="goods-article">
          <!-- 商品详情 -->
          <div class="goods-tabs">
            <GoodsDetail :goodsDetail="goodsDetail"></GoodsDetail>
          </div>
        </div>
        <!-- 24热榜+专题推荐 -->
        <div class="goods-aside">
          <GoodsHot :type="1" />
          <GoodsHot :type="2" />
          <GoodsHot :type="3" />
        </div>
      </div>
    </div>
  </div>
</template>

<style scoped lang="less">
// 商品信息
.goods-info {
  min-height: 600px;
  background: #fff;
  display: flex;

  .media {
    width: 580px;
    height: 600px;
    padding: 30px 50px;
  }

  .spec {
    flex: 1;
    padding: 30px 30px 30px 0;
  }
}

// 图片预览区
.goods-image {
  width: 480px;
  height: 400px;
  background-color: #eee;
}

// 统计数量
.goods-sales {
  display: flex;
  width: 400px;
  align-items: center;
  text-align: center;
  height: 140px;

  li {
    flex: 1;
    position: relative;

    ~li::after {
      position: absolute;
      top: 10px;
      left: 0;
      height: 60px;
      border-left: 1px solid #e4e4e4;
      content: '';
    }

    p {
      color: #999;
    }

    &:nth-child(2) {
      color: @priceColor;
      margin-top: 10px;
    }

    &:last-child {
      color: #666;
      margin-top: 10px;

      i {
        color: @xtxColor;
        font-size: 14px;
        margin-right: 2px;
      }

      &:hover {
        color: @xtxColor;
        cursor: pointer;
      }
    }
  }
}

// 商品信息区
.spec {
  .g-name {
    font-size: 22px;
  }

  .g-desc {
    color: #999;
    margin-top: 10px;
  }

  .g-price {
    margin-top: 10px;

    span {
      &::before {
        content: '¥';
        font-size: 14px;
      }

      &:first-child {
        color: @priceColor;
        margin-right: 10px;
        font-size: 22px;
      }

      &:last-child {
        color: #999;
        text-decoration: line-through;
        font-size: 16px;
      }
    }
  }

  .g-service {
    background: #f5f5f5;
    width: 500px;
    padding: 20px 10px 0 10px;
    margin-top: 10px;

    dl {
      padding-bottom: 20px;
      display: flex;
      align-items: center;

      dt {
        width: 50px;
        color: #999;
      }

      dd {
        color: #666;

        &:last-child {
          span {
            margin-right: 10px;

            &::before {
              content: '•';
              color: @xtxColor;
              margin-right: 2px;
            }
          }

          a {
            color: @xtxColor;
          }
        }
      }
    }
  }
}

.goods-footer {
  display: flex;
  margin-top: 20px;

  .goods-article {
    width: 940px;
    margin-right: 20px;
  }

  .goods-aside {
    width: 280px;
    min-height: 1000px;
  }
}

.goods-tabs {
  min-height: 600px;
  background: #fff;
}

.goods-warn {
  min-height: 600px;
  background: #fff;
  margin-top: 20px;
}

.goods-info.xtx-loading {
  background: #fff url('@/assets/images/loading.gif') no-repeat center;
}
</style>

​
